import { dev, manifest } from "@/env.js"
import { server } from "@/index.js"
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js"
import { StreamableHTTPServerTransport } from "@modelcontextprotocol/sdk/server/streamableHttp.js"
import chalk from "chalk"
import { Command } from "commander"
import { randomUUID } from "node:crypto"
import { createServer } from "node:http"
import { exit } from "node:process"

async function runStdio() {
  await server.connect(new StdioServerTransport())
  const devPrefix = dev ? `[${chalk.cyan.bold("dev_mode".toUpperCase())}] ` : ""
  console.error(chalk.green(`${manifest.name} MCP connected...`))
  console.error(
    chalk.dim(`${devPrefix}Welcome to ${manifest.name} MCP version ${manifest.version}\n`),
  )
}

async function runHttp(port: number) {
  const transport = new StreamableHTTPServerTransport({
    sessionIdGenerator: () => randomUUID(),
  })
  await server.connect(transport)
  const httpServer = createServer((req, res) => {
    transport.handleRequest(req, res).catch((err) => {
      console.error(err)
      res.writeHead(500).end("Internal Server Error")
    })
  })
  httpServer.listen(port, () => {
    console.error(chalk.green(`HTTP server listening on port ${port}`))
    console.error(chalk.dim(`Use curl to interact with tools and resources.`))
  })
}

function main() {
  const program = new Command()

  program.name(manifest.name).description(`${manifest.name} MCP server`).version(manifest.version)

  program
    .command("stdio")
    .description("Run MCP server in stdio mode (default)")
    .action(async () => {
      try {
        await runStdio()
      } catch (err) {
        console.error(`failed to run mcp server: ${chalk.dim(err)}`)
        exit(1)
      }
    })

  program
    .command("http")
    .description("Run MCP server in HTTP mode")
    .option("-p, --port <number>", "Port to listen on", "3000")
    .action(async (options) => {
      const port = parseInt(options.port, 10)
      try {
        await runHttp(port)
      } catch (err) {
        console.error(`failed to start http server: ${chalk.dim(err)}`)
        exit(1)
      }
    })

  program.parse()
}

main()
